import pandas as pd
import numpy as np
import os
import time

'''
约定：
IPC分类号的规则
    分为三个部分: IPC = 四位字符数字混合编号 + 数字编号一 + 数字编号二
    每行列出的ipc的4位前缀相同
    只有4位的, 表示所有已该前缀
    只要有000/00/0出现即表示(除0*所表示编号之外的编号与该IPC都相同)的IPC均为GREEN_IPC
    分隔符中统一使用不能有英文的符号
字符串列举IPC分类号的格式举例:
    C10B-053/02
    C10L-005/00,005/40-005/48
    C10L-005/40,009/00
    F03C
    F03B
    F03B-013/12 - 013/26
    E02B-009/00 -009/06
    H01L-025/00 , 025/03 , 025/16 , 025/18 , 031/042
    E04C-001/40 ,E04C-001/41,E04C-002/284-002/296
'''


def formatIpcInput(ipcStr):
    ipcList = list()
    if len(ipcStr) < 4 or not ipcStr[0].isalpha():
        print("非法的前缀：{0}".format(ipcStr))
        return []
    prefix = ipcStr[:4]
    ipcStr = ipcStr.replace(prefix, '')
    for ipc in ipcStr.split(','):
        if len(ipc) != 0 and ipc[0] != '-':
            ipc = '-' + ipc
        ipcList.append(prefix + ipc)
    return ipcList


# ipcDict的结构 ==> dict(string, dict(int, list(list(int))))
def setDict(ipcDict, ipcStr):
    prefix = ipcStr[:4]
    if not prefix[0].isalpha() or not prefix[1].isdigit() or not prefix[2].isdigit() or not prefix[3].isalpha():
        return False
    if len(ipcStr) == 4: # 处理只有4位的IPC编号
        ipcDict[prefix] = {}
    if prefix in ipcDict and not ipcDict[prefix]: # 表示前缀为prefix的IPC均为绿色专利
        return True
    ipcStr = ipcStr[5:]
    # print(ipcStr)
    num = []
    for ipc in ipcStr.split('-'):
        numStr = ipc.split('/')
        if len(numStr) != 2 and len(numStr) != 4:
            return False
        else:
            for n in numStr:
                if not n.strip().isdigit():
                    print("格式错误，不是数字：\"{0}\"".format(n))
                    return False
                # print([n.lstrip('0')])
                num.append(int(n.strip()))

    if len(num) != 2 and len(num) != 4:
        return False
    if prefix in ipcDict: # 字典中已经存在该前缀的IPC
        if num[0] in ipcDict[prefix]:
            if len(num) == 4:
                if num[0] != num[2]:
                    print("不支持的格式：{0}".format(ipcStr))
                    return False
                ipcDict[prefix][num[0]].append([[num[1], num[3]]])
            else:
                ipcDict[prefix][num[0]].append([[num[1]]])
        else:
            if len(num) == 4:
                if num[0] != num[2]:
                    print("不支持的格式：{0}".format(ipcStr))
                    return False
                ipcDict[prefix][num[0]] = [[num[1], num[3]]]
            else:
                ipcDict[prefix][num[0]] = [[num[1]]]
    else:
        if len(num) == 4:
            if num[0] != num[2]:
                print("不支持的格式：{0}".format(ipcStr))
                return False
            ipcDict[prefix] = {num[0]:[[num[1], num[3]]]}
        else:
            ipcDict[prefix] = {num[0]:[[num[1]]]}

    if num[0] == 0: # 特殊处理000/00/0
        ipcDict[prefix] = {}
    else:
        if num[1] == 0:
            ipcDict[prefix].pop(num[0])
            ipcDict[prefix][num[0]] = []
    return True


def getIpcDict(greenIpcExcelFileName):
    # 直接默认读取这个Excel的第一个表单
    sheet = pd.read_excel(greenIpcExcelFileName) # 返回一个DataFrame
    ipcColumn = sheet.values[:,4] # 获取第5列的所有数据，对应第二个IPC分类号那一列
    # print(type(ipcColumn)) # 查看返回值类型
    print("总共有{0}行".format(ipcColumn.size))

    ipcList = list() # 创建一个空的list数组，用来存储格式化后的IPC字符串
    ipcDict = dict() # 创建一个空的dict字典
    cnt = 0
    for i in ipcColumn:
        if type(i) != float: # 只保留str类型的数据
            for str in i.splitlines():
                ipcList.extend(formatIpcInput(str))
                cnt += 1
    # print("----------%d: \"%s\"" %(cnt, str))
    print("绿色专利号字符串共有：{0}个".format(len(ipcList)))

    for ipc in ipcList:
        if not setDict(ipcDict, ipc):
            print("格式错误：{0}".format(ipc))
        # print("\"{0}\"".format(ipc)) # 查看格式化之后的IPC编号
    print("生成的IPC字典")
    print(ipcDict)
    return ipcDict


def getIpcArrayOfCompany(companyIpcExcelFileName):
    sheet = pd.read_excel(companyIpcExcelFileName)
    ipcArray = list() # 创建一个数组
    ipcMainClassList = sheet['IPC主分类'].tolist() # 获取IPC主分类这一列的数据
    ipcDataList = sheet['申请日'].tolist() # 获取申请年份
    ipcYearList = []
    for ipcData in ipcDataList: # 获取年份
        ipcYearList.append(ipcData.year)
    cnt = 0
    for i in ipcMainClassList:
        if type(i) == float:
            continue
        tmp = i.split('/')
        # 每一个ipc用一个三元组来唯一表示
        # 第一个元素为，ipc的四位前缀，为字符串类型；后两个元素记录标号，为整型
        if not tmp[0][4:].isdigit() or not tmp[1].isdigit():
            print("格式错误，不是数字：\"{0}\"".format(i))
            continue
        ipcTuple = (tmp[0][0:4], int(tmp[0][4:]), int(tmp[1]), ipcYearList[cnt])
        ipcArray.append(ipcTuple)
        cnt += 1
    # print(ipcTuple)
    # print("----------%d: \"%s\"" %(cnt, i))
    return ipcArray


def isGreenIpc(ipcDict, ipc):
    if ipc[0] in ipcDict:
        if ipcDict[ipc[0]] == {}:
            return True
        else:
            if ipc[1] in ipcDict[ipc[0]]:
                if ipcDict[ipc[0]][ipc[1]] == []:
                    return True
                for iList in ipcDict[ipc[0]][ipc[1]]:
                    if len(iList) == 2: # 处理区间
                        if ipc[2] >= iList[0] and ipc[2] <= iList[1]:
                            return True
                    else:
                        if ipc[2] == iList[0]:
                            return True
    return False


def getNumOfGreenIpc(ipcDict, ipcArray):
    numOfGreenIpc = 0
    for ipc in ipcArray:
        if isGreenIpc(ipcDict, ipc):
            numOfGreenIpc += 1
    return numOfGreenIpc


def getNumOfGreenIpcInYear(ipcDict, ipcArray):
    companyIpcDictInYear = dict()
    for ipc in ipcArray:
        if isGreenIpc(ipcDict, ipc):
            if ipc[3] in companyIpcDictInYear:
                companyIpcDictInYear[ipc[3]] += 1
            else:
                companyIpcDictInYear[ipc[3]] = 1
    # print(companyIpcDictInYear)
    companyIpcDictInYear = sorted(companyIpcDictInYear.items(), key = lambda d: d[0]) # 按年份排序
    return companyIpcDictInYear


def prepareTableData(ipcDict, companyPatentExcelDir):
    fileList = os.listdir(companyPatentExcelDir) # 运行该程序的时候不要用Excel打开文件夹中的文件，打开的时候会有临时文件多出来
    table = pd.DataFrame()
    companyStockCodeList = list()
    companyNameList = list()
    yearList = list()
    numList = list()
    for fileName in fileList:
        filePath = companyPatentExcelDir + '/' + fileName
        ipcArrayOfCompany = getIpcArrayOfCompany(filePath)
        numOfGreenIpc = getNumOfGreenIpc(ipcDict, ipcArrayOfCompany)
        print("\n{0}中共有{1}个绿色专利".format(fileName, numOfGreenIpc))
        companyIpcDictInYear = getNumOfGreenIpcInYear(ipcDict, ipcArrayOfCompany)
        print(companyIpcDictInYear)

        # table = prepareTableData(companyIpcDictInYear, fileName)
        # print(table)

        companyStockCode = fileName.split(' ')[1]
        companyName = fileName.split(' ')[-1].split('.')[0]
        for pair in companyIpcDictInYear:
            # print(pd.Series([pair[0], pair[1]], index = ["年份", "专利数量"]))
            companyStockCodeList.append(companyStockCode)
            companyNameList.append(companyName)
            yearList.append(pair[0])
            numList.append(pair[1])
    dict = {
            "股票代码":companyStockCodeList,
            "公司名":companyNameList,
            "年份":yearList,
            "绿色专利申请量":numList
        }
    table = pd.DataFrame(dict)
    return table


def main():
    greenIpcFileName = 'ipc green inventory 整理全面版.xlsx'
    ipcDict = getIpcDict(greenIpcFileName)
    companyPatentExcelDir = './all_company_patent_excel'
    prepareTableData(ipcDict, companyPatentExcelDir).to_excel("statistic.xlsx")


if __name__ == '__main__': # 直接运行此文件则为True，以模块的方式导入时为False

    main()


'''
# ipcDict的结构 ==> dict(string, list(dict(int, list(int))))
def setDict(ipcDict, ipcStr): # _RetiredVersion
    prefix = ipcStr[:4]
    if len(ipcStr) == 4: # 处理只有4位的IPC编号
        ipcDict[prefix] = {}
    if prefix in ipcDict and not ipcDict[prefix]: # 表示前缀为prefix的IPC均为绿色专利
        return
    ipcStr = ipcStr[5:]
    # print(ipcStr)
    num = []
    for ipc in ipcStr.split('-'):
        numStr = ipc.split('/')
        for n in numStr:
            num.append(int(n))

    if prefix in ipcDict: # 字典中已经存在该前缀的IPC
        if len(num) == 2:
            ipcDict[prefix].append({num[0]:[num[1]]})
        else:
            ipcDict[prefix].append({num[0]:[num[1], num[3]]})
    else:
        if len(num) == 2:
            ipcDict[prefix] = [{num[0]:[num[1]]}]
        else:
            ipcDict[prefix] = [{num[0]:[num[1], num[3]]}]

    if num[0] == 0: # 特殊处理000/00/0
        ipcDict[prefix] = []
    else:
        if num[1] == 0:
            for ipcD in ipcDict[prefix]:
                if num[0] in ipcD:
                    ipcDict[prefix].remove(ipcD)
            ipcDict[prefix].append([{num[0]:[]}])
    return
'''
